package com.zxy.ziems.server.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.common.response.PageResult;
import com.zxy.btp.common.util.BCRSAUtil;
import com.zxy.btp.common.util.SpringContextUtils;
import com.zxy.btp.mybatis.base.BtpBaseServiceImpl;
import com.zxy.btp.security.service.PasswordService;
import com.zxy.btp.web.util.TokenUtils;
import com.zxy.ziems.server.constant.enums.UserStatusEnum;
import com.zxy.ziems.server.convert.UserConvert;
import com.zxy.ziems.server.domain.Resource;
import com.zxy.ziems.server.domain.Role;
import com.zxy.ziems.server.domain.RoleResourceRel;
import com.zxy.ziems.server.domain.User;
import com.zxy.ziems.server.dto.*;
import com.zxy.ziems.server.foms.dto.TenantUser;
import com.zxy.ziems.server.foms.dto.UserInfo;
import com.zxy.ziems.server.foms.dto.UserQparams;
import com.zxy.ziems.server.foms.service.FomsRpcService;
import com.zxy.ziems.server.mapper.UserMapper;
import com.zxy.ziems.server.prop.JceProperties;
import com.zxy.ziems.server.service.RoleService;
import com.zxy.ziems.server.service.UserRoleRelService;
import com.zxy.ziems.server.service.UserService;
import com.zxy.ziems.server.vo.RoleVo;
import com.zxy.ziems.server.vo.UserInfoVo;
import com.zxy.ziems.server.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (TUser)表服务实现类
 *
 * @author makejava
 * @since 2023-11-17 10:29:10
 */
@Service
@Slf4j
public class UserServiceImpl extends BtpBaseServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JceProperties jceProperties;
    @Autowired
    private UserRoleRelService userRoleRelService;

    @Autowired
    private RoleService roleService;
    @Autowired
    private FomsRpcService fomsRpcService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertOrUpdate(UserDto userDto) {
        String userId = userDto.getUserId();
        User user = UserConvert.INSTANCE.userDtoToUser(userDto);
        checkPhone(userDto);
        if (StrUtil.isEmpty(userId)) {
            //设置默认密码
            PasswordService passwordService = SpringContextUtils.getBean(PasswordService.class);
            String defaultPassword = jceProperties.getDefaultPassword();
            user.setPassword(passwordService.encode(defaultPassword));
            user.setStatus(UserStatusEnum.START.code());
            userMapper.insert(user);
        } else {
            userMapper.updateById(user);
        }
    }

    private void checkPhone(UserDto userDto) {
        String userId = userDto.getUserId();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(userId)) {
            User user = userMapper.selectById(userId);
            if (!userDto.getPhone().equals(user.getPhone())) {
                throw new ConditionException("手机号不允许修改");
            }
        } else {
            queryWrapper.lambda().eq(User::getPhone, userDto.getPhone());
            List<User> userList = userMapper.selectList(queryWrapper);
            if (CollectionUtil.isNotEmpty(userList)) {
                throw new ConditionException("手机号重复，请修改后再添加");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void stopOrStart(UserDto userDto) {
        String status = userDto.getStatus();
        if (StrUtil.isEmpty(status)) {
            throw new ConditionException("状态不能为空");
        }
        String userId = userDto.getUserId();
        if (StrUtil.isEmpty(userId)) {
            throw new ConditionException("用户id不能为空");
        }
        User user = new User();
        user.setUserId(userId);
        user.setStatus(status);
        userMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void divideRole(UserRoleDto userRoleDto) {
        List<String> roleIdList = userRoleDto.getRoleIdList();
        if (CollectionUtil.isEmpty(roleIdList)) {
            throw new ConditionException("角色id不能为空");
        }
        String userId = userRoleDto.getUserId();
        if (StrUtil.isEmpty(userId)) {
            throw new ConditionException("用户id不能为空");
        }
        userRoleRelService.batchInsert(roleIdList, userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPassword(String userId) {
        User user = new User();
        user.setUserId(userId);
        PasswordService passwordService = SpringContextUtils.getBean(PasswordService.class);
        user.setPassword(passwordService.encode(jceProperties.getDefaultPassword()));
        userMapper.updateById(user);
    }

    @Override
    public void changePassword(ChangePwdDto changePwdDto) {
        checkOldPwd(changePwdDto);
        checkNewPwd(changePwdDto);
    }

    @Override
    public PageResult<UserVo> pageList(UserQueryDto userQueryDto) {
        Page<UserVo> page = new Page<>(userQueryDto.getPageNo(), userQueryDto.getPageSize());
        Page<UserVo> selectPage = userMapper.selectUserList(page, userQueryDto);
        List<UserVo> userVoList = selectPage.getRecords();
        if (ObjectUtil.isEmpty(userVoList)) {
            return new PageResult<>(0L, new ArrayList<>());
        }
        //根据用户id查询角色数据
        List<String> userIdList = userVoList.stream().map(UserVo::getUserId).collect(Collectors.toList());
        List<RoleVo> roleVoList = userRoleRelService.selectListByUserId(userIdList);
        //匹配数据
        if (CollectionUtil.isNotEmpty(roleVoList)) {
            Map<String, List<RoleVo>> map = roleVoList.stream().collect(Collectors.groupingBy(RoleVo::getUserId));
            for (UserVo userVo : userVoList) {
                List<RoleVo> voList = map.get(userVo.getUserId());
                if (CollectionUtil.isNotEmpty(voList)) {
                    userVo.setRoleVoList(voList);
                }
            }
        }
        return new PageResult(selectPage.getTotal(), userVoList);
    }

    private void checkOldPwd(ChangePwdDto changePwdDto) {
        //校验旧密码是否正确
        String oldPassword = "";
        try {
            oldPassword = BCRSAUtil.decrypt(changePwdDto.getOldPassword());

        } catch (Exception e) {
            log.info("密码解密失败，错误信息为：{}", e.getMessage());
            e.printStackTrace();
            throw new ConditionException("密码解密失败，请联系管理员");
        }
        User user = userMapper.selectById(TokenUtils.getUserIdByToken());
        if (ObjectUtil.isEmpty(user)) {
            throw new ConditionException("未查询到该用户");
        }
        PasswordService passwordService = SpringContextUtils.getBean(PasswordService.class);
        if (!passwordService.match(oldPassword, user.getPassword())) {
            throw new ConditionException("原密码输入错误，请重新输入");
        }
    }

    private void checkNewPwd(ChangePwdDto changePwdDto) {
        String newPwd = null;
        try {
            newPwd = BCRSAUtil.decrypt(changePwdDto.getNewPassword());

        } catch (Exception e) {
            log.info("密码解密失败，错误信息为：{}", e.getMessage());
            e.printStackTrace();
            throw new ConditionException("密码解密失败，请联系管理员");
        }
        User user = new User();
        user.setUserId(TokenUtils.getUserIdByToken());
        PasswordService passwordService = SpringContextUtils.getBean(PasswordService.class);
        user.setPassword(passwordService.encode(newPwd));
        userMapper.updateById(user);
    }

    @Override
    public UserInfoVo getUserInfo(String userId) {
        UserInfoVo userInfo = new UserInfoVo();

//        UserVo user = baseMapper.selectUserVoBy(userId);
        UserVo user = new UserVo();
        UserInfo userInfo1 = fomsRpcService.getUserInfo(userId);
        user.setEmail(userInfo1.getEmail());
        user.setOrgId(userInfo1.getDeptId());
        user.setOrgName(userInfo1.getDeptName());
        user.setPhone(userInfo1.getPhone());
        user.setUserId(userInfo1.getId());
        user.setUserName(userInfo1.getName());
        user.setStatus(userInfo1.getStatus());

        List<RoleVo> roleVos = userRoleRelService.selectListByUserId(Collections.singletonList(userId));
        user.setHomeUrl(roleVos.stream().map(RoleVo::getHomePage).filter(StrUtil::isNotEmpty).findFirst().orElse(""));
        user.setRoleVoList(roleVos);
        userInfo.setUser(user);

        List<RoleResourceRel> list = roleService.roleResourceRelListByUserId(userId);

        userInfo.setResourceIdList(list.stream().map(RoleResourceRel::getResourceId)
                .filter(StrUtil::isNotEmpty).distinct().collect(Collectors.toList()));

//        List<ResourceTree> list = roleService.getLoginMenu(userId);
//        //添加根节点
//        ResourceTree resourceTree = new ResourceTree();
//        resourceTree.setResourceId("root");
//        resourceTree.setUrl("root");
//        resourceTree.setChildren(list);
//        if (CollectionUtil.isNotEmpty(list)) {
//            list.stream().forEach(resourceTreeInList -> resourceTreeInList.setParentResourceId("root"));
//        }
//
//        userInfo.setMenuResource(resourceTree);
        return userInfo;
    }

    @Override
    public User loadById(String id) {
        return baseMapper.selectById(id);
    }

    @Override
    public List<User> listByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtil.isEmpty(idList)) {
            return new ArrayList<>(0);
        }
        return super.listByIds(idList);
    }

    @Override
    public PageResult<UserVo> pageListFoms(UserQueryDto userQueryDto) {

        UserQparams param = new UserQparams();
        param.setPageNo(userQueryDto.getPageNo().intValue());
        param.setPageSize(userQueryDto.getPageSize().intValue());
        param.setName(userQueryDto.getUserName());
        param.setDeptId(userQueryDto.getOrgId());

        IPage<UserInfo> userInfoIPage = fomsRpcService.pageList(param);
//        Page<UserVo> selectPage = userMapper.selectUserList(page, userQueryDto);
        List<UserInfo> records = userInfoIPage.getRecords();
        List<UserVo> userVoList = records.stream().map(m -> fomsUserToEmsUser(m)).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(userVoList)) {
            return new PageResult<>(0L, new ArrayList<>());
        }
        //根据用户id查询角色数据
        List<String> userIdList = userVoList.stream().map(UserVo::getUserId).collect(Collectors.toList());
        List<RoleVo> roleVoList = userRoleRelService.selectListByUserId(userIdList);
        //匹配数据
        if (CollectionUtil.isNotEmpty(roleVoList)) {
            Map<String, List<RoleVo>> map = roleVoList.stream().collect(Collectors.groupingBy(RoleVo::getUserId));
            for (UserVo userVo : userVoList) {
                List<RoleVo> voList = map.get(userVo.getUserId());
                if (CollectionUtil.isNotEmpty(voList)) {
                    userVo.setRoleVoList(voList);
                }
            }
        }
        return new PageResult(userInfoIPage.getTotal(), userVoList);
    }

    private UserVo fomsUserToEmsUser(UserInfo m) {
        UserVo userVo = new UserVo();
        userVo.setOrgId(m.getDeptId());
        userVo.setOrgName(m.getDeptName());
        userVo.setPhone(m.getPhone());
        userVo.setUserId(m.getId());
        userVo.setUserName(m.getName());
        userVo.setStatus(m.getStatus());
        return userVo;
    }

    @Override
    public void initResources(TenantUser tenantUser) {
        if (Integer.valueOf(1).equals(tenantUser.getType())) { // 超级管理员
            List<String> userRoles = userRoleRelService.selectRoleIdList(tenantUser.getUserId());
            if (CollectionUtils.isEmpty(userRoles)) {
                List<Role> list = roleService.list(new RoleQueryDto());
                //增加admin角色
                List<String> roleIdList = list.stream().map(Role::getRoleId).collect(Collectors.toList());
                userRoleRelService.batchInsert(roleIdList, tenantUser.getUserId());
            }
        }
    }
}

